package com.example.videopractice.media

import android.Manifest
import android.media.MediaCodec
import android.media.MediaExtractor
import android.media.MediaFormat
import android.media.MediaMuxer
import android.os.Bundle
import android.os.Environment
import com.example.base.base.BaseBindingActivity
import com.example.base.util.ALog
import com.example.videopractice.databinding.ActivityMediaBinding
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File
import java.nio.ByteBuffer


/**
 *  MediaExtractor和MediaMuxer讲解
 */
class MediaActivity : BaseBindingActivity<ActivityMediaBinding>() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        requestMultiplePermissions.launch(
            arrayOf(
                Manifest.permission.READ_EXTERNAL_STORAGE,
                Manifest.permission.WRITE_EXTERNAL_STORAGE,
                Manifest.permission.RECORD_AUDIO
            )
        )

        binding.btnMediaExtractor.setOnClickListener {
            GlobalScope.launch(Main) {
                try {
                    binding.btnMediaExtractor.isEnabled = false
                    withContext(IO) { onMediaExtractor() }
                } catch (e: Exception) {
                    ALog.e("xiao", "error: ${e.message}")
                    e.printStackTrace()
                } finally {
                    binding.btnMediaExtractor.isEnabled = true
                }
            }
        }
        binding.btnEx.setOnClickListener {
            GlobalScope.launch(Main) {
                try {
                    binding.btnEx.isEnabled = false
                    withContext(IO) {
                        val isSuccess = ex()
                        ALog.e("xiao", "提取成功? $isSuccess")
                    }
                } catch (e: Exception) {
                    ALog.e("xiao", "error: ${e.message}")
                    e.printStackTrace()
                } finally {
                    binding.btnEx.isEnabled = true
                }
            }
        }
    }

    /**
     * MediaExtractor的作用是把音频和视频的数据进行分离。
     */
    private fun onMediaExtractor() {
        val path =
            Environment.getExternalStorageDirectory().absolutePath + File.separator + "test.mp4"
        val extractor = MediaExtractor()
        //1.设置数据源
        extractor.setDataSource(path)
        val numTracks = extractor.trackCount
        ALog.e("xiao", "源文件通道数: $numTracks")
        for (i in 0 until numTracks) {
            ALog.e("xiao", "*******")
            //2.分离轨道
            val format = extractor.getTrackFormat(i)
            val mime = format.getString(MediaFormat.KEY_MIME)
            ALog.e("xiao", "mime: $mime")
            //3.选择轨道
            extractor.selectTrack(i)
            val inputBuffer =
                ByteBuffer.allocate(format.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE)) //获取视频缓存输出的最大大小
            //4.读取数据
            while (true) {
                val readSampleDataSize = extractor.readSampleData(inputBuffer, 0)
                if (readSampleDataSize < 0) break
                ALog.e("xiao", "trackIndex: ${extractor.sampleTrackIndex}")
                ALog.e("xiao", "presentationTimeUs: ${extractor.sampleTime}")
                // 其他操作省略
                //5.下一帧
                extractor.advance()
            }
        }
        //6.释放
        extractor.release()
    }

    //从MP4文件中提取视频并生成新的视频文件
    private fun ex(): Boolean {
        val sourcePath =
            Environment.getExternalStorageDirectory().absolutePath + File.separator + "test.mp4"
        val outputPath =
            Environment.getExternalStorageDirectory().absolutePath + File.separator + "output.mp4"
        val mediaExtractor = MediaExtractor()
        var mediaMuxer: MediaMuxer? = null
        mediaExtractor.setDataSource(sourcePath)
        var videoTrackIndex = -1
        var frameRate = 0
        val numTracks = mediaExtractor.trackCount
        for (i in 0 until numTracks) {
            val format = mediaExtractor.getTrackFormat(i)
            val mime = format.getString(MediaFormat.KEY_MIME) ?: continue
            if (!mime.startsWith("video/")) {
                continue
            }
            frameRate = format.getInteger(MediaFormat.KEY_FRAME_RATE)
            mediaExtractor.selectTrack(i)
            mediaMuxer = MediaMuxer(outputPath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4)
            videoTrackIndex = mediaMuxer.addTrack(format)
            mediaMuxer.start()
        }

        val _mediaMuxer = mediaMuxer ?: return false
        val info = MediaCodec.BufferInfo()
        info.presentationTimeUs = 0
        val buffer = ByteBuffer.allocate(500 * 1024)
        var sampleSize = 0
        while (true) {
            sampleSize = mediaExtractor.readSampleData(buffer, 0)
            if (sampleSize <= 0) break

            info.offset = 0
            info.size = sampleSize
            info.flags = MediaCodec.BUFFER_FLAG_KEY_FRAME
            info.presentationTimeUs += 1000 * 1000 / frameRate
            _mediaMuxer.writeSampleData(videoTrackIndex, buffer, info)
            mediaExtractor.advance()
        }

        mediaExtractor.release()

        _mediaMuxer.stop()
        _mediaMuxer.release()

        return true
    }
}